import cv2
import tkinter as tk
import numpy as np


def process_tic_tac_toe_board(image, square_size=1000, min_area_threshold=500, max_area_threshold=100000,
                              overlap_threshold=50):
    # 输入验证：检查 image 是否为有效图像
    if not isinstance(image, np.ndarray):
        raise ValueError(f"Invalid image: {image}. Please provide a valid image array.")

    # 使用 tkinter 获取屏幕分辨率
    root = tk.Tk()
    screen_width = root.winfo_screenwidth()
    screen_height = root.winfo_screenheight()
    root.destroy()

    # 获取图像的大小
    original_height, original_width = image.shape[:2]

    # 计算图像中心位置
    center_y = original_height // 2
    center_x = original_width // 2

    # 计算正方形区域的左上角和右下角坐标
    top_left_y = max(center_y - square_size // 2, 0)
    top_left_x = max(center_x - square_size // 2, 0)
    bottom_right_y = min(center_y + square_size // 2, original_height)
    bottom_right_x = min(center_x + square_size // 2, original_width)

    # 截取图像中心的正方形区域
    square_image = image[top_left_y:bottom_right_y, top_left_x:bottom_right_x]

    # 将正方形图像转换为灰度图像
    gray_image = cv2.cvtColor(square_image, cv2.COLOR_BGR2GRAY)

    # 进行中值滤波以去噪
    median_filtered_image = cv2.medianBlur(gray_image, 5)

    # 对灰度图像进行二值化处理
    _, binary_image = cv2.threshold(median_filtered_image, 60, 255, cv2.THRESH_BINARY)

    # 进行高斯模糊
    Gaussian_image = cv2.GaussianBlur(binary_image, (7, 7), 0)

    # 提取图像边缘
    edges = cv2.Canny(Gaussian_image, 100, 200)

    # 使用 Hough 变换检测直线
    lines = cv2.HoughLinesP(edges, 1, np.pi / 180, threshold=50, minLineLength=200, maxLineGap=100)
    lines_image = square_image.copy()
    lines_image[:] = 0

    height, width = lines_image.shape[:2]

    # 检查 lines 是否为 None
    if lines is not None:
        for index, line in enumerate(lines):
            x1, y1, x2, y2 = line[0]

            if x2 - x1 != 0:  # 避免除以零
                slope = (y2 - y1) / (x2 - x1)
                intercept = y1 - slope * x1

                # 计算延长线的两个端点
                y1_extended = int(slope * 0 + intercept)  # 当x=0时的y
                y2_extended = int(slope * width + intercept)  # 当x=width时的y
                cv2.line(lines_image, (0, y1_extended), (width - 1, y2_extended), (255, 255, 255), 20)
            else:
                # 处理垂直线
                cv2.line(lines_image, (x1, 0), (x1, height - 1), (255, 255, 255), 20)

    # 进行高斯模糊
    Gaussian_image_handle = cv2.GaussianBlur(lines_image, (7, 7), 0)

    # 提取图像边缘
    edges_handle = cv2.Canny(Gaussian_image_handle, 100, 200)

    # 找到轮廓
    contours, _ = cv2.findContours(edges_handle, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

    rectangles_image = square_image.copy()
    valid_centers = []

    # 遍历每个轮廓并绘制
    for index, contour in enumerate(contours):
        # 近似轮廓以获取多边形
        epsilon = 0.02 * cv2.arcLength(contour, True)
        approx = cv2.approxPolyDP(contour, epsilon, True)

        # 计算轮廓面积
        area = cv2.contourArea(contour)

        # 检查轮廓面积是否满足阈值
        if area < min_area_threshold or area > max_area_threshold:
            continue

        # 计算矩形的中心点
        M = cv2.moments(approx)
        if M["m00"] != 0:
            cx = int(M["m10"] / M["m00"])
            cy = int(M["m01"] / M["m00"])
            center = (cx, cy)
        else:
            continue

        # 检查中心点是否与已有中心点重合
        is_overlapping = any(
            np.sqrt((cx - prev_cx) ** 2 + (cy - prev_cy) ** 2) < overlap_threshold for prev_cx, prev_cy in
            valid_centers)

        if not is_overlapping:
            cv2.polylines(rectangles_image, [approx], isClosed=True, color=(0, 255, 0), thickness=1)
            valid_centers.append(center)

            # 在中心点处打点
            cv2.circle(rectangles_image, center, 5, (0, 0, 255), -1)

            # 在中心点处标注序号和坐标
            cv2.putText(rectangles_image, f"{len(valid_centers)}: ({cx}, {cy})", (cx, cy),
                        cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 0), 2)

    return rectangles_image, valid_centers


# 使用示例
if __name__ == "__main__":
    image_path = r"E:\Desktop\TI2024\TI2024_E_python\test_image\ChessBord004.jpg"
    image = cv2.imread(image_path)

    if image is not None:
        output_image, coordinates = process_tic_tac_toe_board(image)
        cv2.imshow("Processed Image", output_image)
        print("Valid center coordinates:", coordinates)
        cv2.waitKey(0)
        cv2.destroyAllWindows()
    else:
        print("Error: Image not found.")
